perm filename DEFVST.INF[LIB,LSP] blob sn#577503 filedate 1981-04-09 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00004 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	  DEFVST is an acronym for "DEFine a Vector-like STructure"
C00007 00003	  The SETVST macro (and SETF) is used in conjunction with DEFVST.  The 
C00014 00004	  CONSTRAINTS, and INITIAL VALUES
C00023 ENDMK
C⊗;
  DEFVST is an acronym for "DEFine a Vector-like STructure"
    All entries in a Vector-like structure are "pointers" (FIXNUMs, LISTs, etc)
    Future plans call for
	DEFBST		-  "DEFine a Bitstring-like STructure", useful where
			     the structure is an interface to some memory
			     block required to be sequential by, say, operating
			     system conventions, or hardware needs.
	DEFSTRUCT 	-  "DEFine a general STRUCTure"
 			    which will be done by composing DEFVST and DEFBST.
  Vector-like structures are implemented as EXTENDs, which are emulated in
     maclisp by HUNKs, and on the LISPMachine by 1-dimensional
    ART-Q arrays;  EXTENDs interface to a CLASS system, which interface
    well be activated at any time when the CLASS system is loaded -- 
    only a skeletal amount of information is necessary in each class
    of vector-like structures in order to prepare for the link-up.

  Free (global) variables controlling actions:
	CONSTRUCTOR-NAMESTRING-PREFIX 	- constructor name is obtained by 
					  concatenating this string with the
					  structure name.
	SELECTOR-NAMESTRING-STYLE	- ()    ==> selector macro name is same
						    as keyword (variable name).
					- "xxx" ==> selector macro name gotten
						    by concatenating structure 
						    name, "xxx", and keyword.

  Basic macros: 	DEFVST  for defining a structure
			SETVST  for updating a selected component
			  (and SETF)
  Additional functions: 
	STRUCT-TYPEP  for "structures", returns the given name,
		and for non-structures, returns ().
	|defvst-construction/||,  |defvst-initialize/||,  |defvst-typchk/||,
	|defvst-construction-1/||,  |defvst-selection/||, and |defvst-xref/||
		are internal helper functions.

  Usage is like:
	(DEFVST SHIP 
		(X-POSITION /: FIXNUM) 
		Y-POSITION 
		(MASS = 1000.) 
 	 	(COST (DAY-HIGH-PRICE))
		COLOR )
	(SETVST (SHIP-X-POSITION QE2) 109.)
  or alternatively, 
	(SETF (SHIP-X-POSITION QE2) 109.)
  since SETF will macroexpand out the component selector, and thus turn 
  into SETVST, on structures references.  Also, a set of "options" may
  be specified by including the structure name in a list:
	(DEFVST (SHIP <option1> <option2> ...)  ...)
  currently, only :CONSTRUCTOR and :NO-SELECTOR-MACROS are valid options.
 
  Note that "=" is used as a keyword in the component part to mean
  an initialization form follows; and that a component specification
  which is just a 2-list is expanded like 
 	   (<component-name> <form>)  ==>  (<component-name> = <form>)
  This is done for compatibility of style with the LISPM defstructure.
  See further notes below for the meaning of the ":" in  the default form.

  The SETVST macro (and SETF) is used in conjunction with DEFVST.  The 
  example use of DEFVST "defines" a vector-like structure of 4 components;  
  the generic name of this structure is "SHIP", and the components are 
  identified by the ordering of what are called keywords -  X-POSITION, 
  Y-POSITION, MASS, and COLOR.  Each "definition" causes the creation of 
      1) A constructor macro, whose name (normally) is obtained by prefixing
	 the string "CONS-A-" onto the generic name of the structure.
	 (Actually, it gets this prefix string from the variable 
	  CONSTRUCTOR-NAMESTRING-PREFIX, so that it can be modified)
	 In the example, this becomes CONS-A-SHIP.  The constructor
	 permits installing values into the component slots at instantiation
	 time, which are evaluated from either the (default) forms supplied 
	 by the invocation of DEFVST, or from the forms obtained by keyword 
	 parameters in the instantiating form.  E.g. 
		(CONS-A-BANK DOLLARS (PLUS 300. WALLET) MANAGER '|Jones, J.|)
	 would put the numerical value of  300.+WALLET  in the DOLLARS 
	 component of a newly-created bank, and install |Jones, J.| as 
	 its MANAGER.   When the :CONSTRUCTOR option is given, the user
	 supplies a specific name for this macro.
      2) N selector macros, one for each keyword (which denotes one
	 component slot), which are obtained (normally) by concatenating
	 the generic name, a "-", and the keyword name.   (Actually,
	 the middle string is obtained from the value of the variable
	 SELECTOR-NAMESTRING-STYLE, so that it can be modified)
	 In the example, we have SHIP-X-POSITION, SHIP-Y-POSITION, 
	 SHIP-MASS, and SHIP-COLOR.
		2a: (SHIP-X-POSITION QE2) 
		     to obtain the x-coordinate of QE2
		2b: (SETVST (SHIP-X-POSITION QE2) 109.)
		     to change the x-coordinate to of QE2 to 109.
	 One interesting facet of the selector macroexpansions is that
	 when done for compilation, the turn into the MacLISP CXR,
	 which can generally be open-coded in one or two instructions.
	 But when expanded during interpretation, the go thru a
	 safety checking function, which assures that a selector
	 created for a SHIP structure is only applied to SHIP structures,
	 and not to other kinds of data, or other structures.
	 When the :NO-SELECTOR-MACROS option is given, then these macros,
	 like SHIP-X-POSITION, are not created;  this is intended to
	 delete the spurious creation of macros, when another macro
	 package is using DEFVST like a subroutine.
      3) An information structure, stored as the STRUCT=INFO property
	 of the generic name symbol.  This information has the shape
		(DEFVST STRUCT=INFO 
			VERSION-NUMBER 
			GENERIC-NAME 	
			CONSTRUCTOR-NAME 
			NUMBER-OF-NAMED-COMPONENTS 
			COMPONENT-DEFAULT-INITIALIZATION-LISTS 
			CLASS-SKELETON)
	The generic name corresponds to the "name" of the structure
	  being defined;  in the example, it is BANK.  The version number
	  corresponds to a version of "implementation status" for DEFVST -- 
	  thus it should be possible to make rather radical changes in
	  the future implementation, while maintain compatibility with
	  previously compiled structures (that means that existing FASL
	  files won't have to be recompiled whenever some change to
	  DEFVST is made).
	The zero'th element of the initializations is either (), or a
	  3-list of the key-name, selector-name, and default size for the
	  &REST component - the "block" of unnamed components in the
	  structure.   The remaining elements of the initializations are
	  the "initialization lists" for each named component:
		(<key-name> <corresponding-selector>)
				;() initial value, no restrictions
		(<key-name> <corresponding-selector> <ini-val-form>)
				;no restrictions
		(<key-name> <corresponding-selector> 
			    <ini-val-form> . <list-of-types-for-restrictions>)
  CONSTRAINTS, and INITIAL VALUES
    Each of the components may be constrained to be a particular 
      type datum, and may be initialized according to the form supplied
      as default by the call to DEFVST.
    The syntax for a non-simple component specification is a list with
      the first element being the key name, the item following the first 
      "=" in the list being a form which is the default form to be evaluated
      for that component in any creations of instances of that structure, 
      and the element following the first ":" is either a type name or list 
      of type names that restricts any creating instance from supplying an 
      initial value of the wrong type.  If a key has a restriction 
      associated with it, but no default initial-value form, then DEFVST 
      picks some default value consistent with the restriction.
	
    Consider the example

	(DEFVST BANK
		(DOLLARS : (FIXNUM FLONUM MUMBLE))
		MANAGER
		(LIMIT : (FIXNUM FLONUM) = 1000000.0)
		&REST
		VAULTS
		30.)

      First, the macro invocation of DEFVST would expand into

	(EVAL-WHEN (EVAL COMPILE LOAD) 
	  (AND (STATUS FEATURE COMPLR) (SPECIAL BANK-CLASS))
	  (|defvst-initialize/|| 
		'BANK
		'CONS-A-BANK
		3
		'#((VAULTS BANK-VAULTS 30.)
		   (DOLLARS BANK-DOLLARS 0 FIXNUM FLONUM MUMBLE)
		   (MANAGER BANK-MANAGER)
		   (LIMIT BANK-LIMIT 1000000.0 FIXNUM FLONUM))
		1)
	  (SETF (GET (SI:CLASS-PLIST (GET 'BANK 'CLASS)) ':SOURCE-FILE)
		 '((AR2 JONL) EXMPL /3))
	  (DEFPROP BANK-VAULTS (BANK 4 &REST) SELECTOR)
	  'BANK)
    The internal function |defvst-initialize/|| creates the STRUCT=INFO
      property for BANK, and sets up macro definitions for all the selector 
      names, and for the constructor name;  also, a "skeleton" is framed
      so that all instances may be grouped into a CLASS of such structures.
      (This information is kept in in the STRUCT=INFO property.)  When the
      CLASS system is actually loaded, the skeletons will be fleshed out
      to the full degree [ see the documentation on the MacLISP SEND
      facility, and on the EXTENDed CLASS system].
    After that, then, a "simple" creation instance will take default values 
      for all components with either initial value or restriction 
      specifications, and null in the unspecified components;  for example
			(CONS-A-BANK)
      then yields an instance, which when printed as a VECTOR, is like
		 #( 0 () 1.0E6 () . . . () )
      namely, a bank with three named components, and with 30. unnamed 
      components which are accessed as if VAULTS were a vector name. 
    Note that the the function CLASS-OF (and also SI:EXTEND-CLASS-OF)
      gets the class descriptor for this class of structures, which
      may be only a "skeleton" when the CLASS system isn't loaded.

    A more complex example of construction, such as, 

	    (CONS-A-BANK DOLLARS (CASEQ VIP 
	    			    (FEDERAL 15.0E9)
	    			    (SAVINGS-&-LOAN 10.0E6)
	    			    (MICKEY-MOUSE 1))
			 MANAGER '|Jones, J.|
 			 LIMIT   (BANK-DOLLARS CURRENT-CONSTRUCTION)
 			 VAULTS  12.)

      illustrates four points of a creating instance - -
	  (1) keywords paired with initial values are just alternating 
	      pairs in the list, and 
	  (2) the forms for initial values are substituted into a piece of
	      code output by the macro, so that they are evaluated at 
	      instantiation time, and
	  (3) the variable CURRENT-CONSTRUCTION is temporarily bound to the
	      structure being created so that it may be referenced; the 
	      installing of initial values happens last.
	  (4) components which are under a restriction, and are not constant 
	      (at compile time) must be submitted to dynamic type checking.
	Notice how this macro-expands -- 

 (LET ((CURRENT-CONSTRUCTION (SI:MAKE-EXTEND 33. BANK-CLASS)))
   (SETVST (BANK-DOLLARS CURRENT-CONSTRUCTION)
	   (|defvst-typchk/|| (CASEQ VIP
				     (FEDERAL 1.5E+10)
				     (SAVINGS-&-LOAN 10000000.0)
				     (MICKEY-MOUSE 1))
			      '(FIXNUM FLONUM MUMBLE)
			      'BANK-DOLLARS))
   (SETVST (BANK-LIMIT CURRENT-CONSTRUCTION)
	   (|defvst-typchk/|| (BANK-DOLLARS CURRENT-CONSTRUCTION)
			      '(FIXNUM FLONUM)
			      'BANK-LIMIT))
   CURRENT-CONSTRUCTION)

    This code might actually not run, since it could stop on a Restriction
      Violation if the variable VIP does not have a value among
	  FEDERAL,  SAVINGS-&-LOAN,  MICKEY-MOUSE
      for then it would turn up a () for the DOLLARS component, which
      was specified to be restricted to fixnums.  

    Further macro-expansion causes the "SETVST"s to become "SI:XSET"s.
      In maclisp, SI:XREF becomes CXR, SI:XSET becomes RPLACX, and
      SI:MAKE-EXTEND becomes MAKHUNK (that is how EXTEND's are emulated 
      there).  Neither the EXTEND package nor any runtime CLASS facilities 
      need be loaded in the runtime environment of code which uses structures,
      since dynamic tests are made before any of these facilites are are used 
      (that is, any facility beyond the MacLISP native HUNK capability).

ββ